package com.desire.test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author desire
 */
public class _43_ReentrantLock重入锁 {
    /**
     * ReentrantLock常常对比着synchronized来分析。
     * （1）synchronized是独占锁，加锁和解锁的过程自动进行，易于操作，但不够灵活。
     * ReentrantLock也是独占锁，加锁和解锁的过程需要手动进行，不易操作，但非常灵活。
     * （2）synchronized可重入，因为加锁和解锁自动进行，不必担心最后是否释放锁；
     * ReentrantLock也可重入，但加锁和解锁需要手动进行，且次数需一样，否则其他线程无法获得锁。
     * （3）synchronized不可响应中断，一个线程获取不到锁就一直等着；
     * ReentrantLock可以相应中断。
     * ReentrantLock好像比synchronized关键字没好太多，
     * synchronized所没有的，一个最主要的就是ReentrantLock还可以实现公平锁机制。
     * 什么叫公平锁呢？也就是在锁上等待时间最长的线程将获得锁的使用权。
     * 通俗的理解就是谁排队时间最长谁先执行获取锁。
     */
    private static final Lock unlock = new ReentrantLock();
    private static final Lock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        new Thread(() -> unfair(), "A").start();
        new Thread(() -> unfair(), "B").start();
        new Thread(() -> unfair(), "C").start();
        new Thread(() -> unfair(), "D").start();
        new Thread(() -> unfair(), "E").start();

/*
        new Thread(() -> fair(), "A").start();
        new Thread(() -> fair(), "B").start();
        new Thread(() -> fair(), "C").start();
        new Thread(() -> fair(), "D").start();
        new Thread(() -> fair(), "E").start();*/
    }

    public static void unfair() {
        unlock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "获取了锁");
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            unlock.unlock();
            System.out.println(Thread.currentThread().getName() + "释放了锁");
        }
    }

    public static void fair() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "获取了锁");
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + "释放了锁");
        }
    }
}
